package com.oa.core.utils;


import com.oa.system.dto.ColumnClass;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;


import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 代码生成工具类型
 * 生成控制层和业务层
 */
public class CodeGenerateUtils {


    private final String CURRENT_DATE = "2019/01/15";
    private static String tableName = ""; //小写
    private static String changeTableName = ""; // 实体类名称
    private final String packageName = "com.jlh.system";
    private static String tableAnnotation = ""; // 模型描述
    private final String AUTHOR = "";

    private final String diskPath = "C:\\Users\\Administrator\\Desktop\\OA\\jlh\\src\\main\\java\\com\\jlh\\system\\";
//    private final String diskPath = "D:\\generate\\";
    private final String corePageName = "com.jlh.core";

    private final String URL = "jdbc:mysql://192.168.0.250:3306/beidou";
    private final String USER = "ycj";
    private final String PASSWORD = "SZmaiji123456";
    private final String DRIVER = "com.mysql.jdbc.Driver";

    public static void main(String[] args) throws Exception{
        List<String> tables = new ArrayList<>();
        tables.add("role");
        tables.add("t_user");

        CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
        codeGenerateUtils.generate(tables);

    }

    public Connection getConnection() throws Exception{
        Class.forName(DRIVER);
        Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);
        return connection;
    }


    public void generate(List<String> tables) throws Exception{
        Map<String,String> map = new HashMap(); // 存放表名称和表注释

        //没有指定表名 则生成数据库中所有表
        if(tables.size() < 1){
            tables = getAllTableName();
        }

        map = getCommentByTableName(tables);

        // 连接数据库
        Connection connection = getConnection();
        for (Map.Entry<String, String> m : map.entrySet()) {
            String table = m.getKey();
            changeTableName = replaceUnderLineAndUpperCase(table);
            tableName = StringUtils.uncapitalize(changeTableName);
            tableAnnotation = m.getValue();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            //1、生成实体文件 (覆盖MybatisGenerator类中生成的实体文件)
            ResultSet resultSet = databaseMetaData.getColumns(null,"%", table,"%");
            generateEntityFile(resultSet,changeTableName);
            //2、生成DTO文件
            generateDTOFile();
            //3、生成mapper文件
            //MybatisGenerator 类中已生成
            //4、生成Dao文件

            //MybatisGenerator 类中已生成
            //5、生成服务层接口文件
            generateServiceInterfaceFile();

            //6、生成服务实现层文件
            generateServiceImplFile();

            //7、生成Controller层文件
            generateControllerFile();

            resultSet.close();

        }

//        connection.close();

        /*
         */
    }

    /**
     * 获取当前数据库下的所有表名称
     * @return
     * @throws Exception
     */
    public List<String> getAllTableName() throws Exception {
        List<String> tables = new ArrayList();
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SHOW TABLES ");
        while (rs.next()) {
            String tableName = rs.getString(1);
            tables.add(tableName);
        }
        rs.close();
        stmt.close();
        conn.close();
        return tables;
    }


    /**
     * 获得某表的建表语句
     * @param tableName
     * @return
     * @throws Exception
     */
    public Map<String,String> getCommentByTableName(List tableName) throws Exception {
        Map<String,String> map = new HashMap();
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();
        for (int i = 0; i < tableName.size(); i++) {
            String table = (String) tableName.get(i);
            ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + table);
            if (rs != null && rs.next()) {
                String createDDL = rs.getString(2);
                String comment = parse(createDDL);
                map.put(table, comment);
            }
            rs.close();
        }
        stmt.close();
        conn.close();
        return map;
    }


    /**
     * 返回注释信息
     * @param all
     * @return
     */

    public static String parse(String all) {
        String comment = null;
        int index = all.indexOf("COMMENT='");
        if (index < 0) {
            return "";
        }
        comment = all.substring(index + 9);
        comment = comment.substring(0, comment.length() - 1);
        return comment;
    }

    public String replaceUnderLineAndUpperCase(String str){
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while(count!=0){
            int num = sb.indexOf("_",count);
            count = num + 1;
            if(num != -1){
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count , count + 1,ia + "");
            }
        }
        String result = sb.toString().replaceAll("_","");
        return StringUtils.capitalize(result);
    }

    /**
     * 生成实体文件
     * @param resultSet
     * @throws Exception
     */
    private void generateEntityFile(ResultSet resultSet,String entityName) throws Exception{

        final String suffix = ".java";
        final String path = diskPath + "entity\\" + entityName + suffix;
        final String templateName = "Entity.ftl";
        File mapperFile = new File(path);
        List<ColumnClass> columnClassList = new ArrayList<>();
        ColumnClass columnClass = null;
        while(resultSet.next()){

            columnClass = new ColumnClass();
            //获取字段名称
            columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
            //获取字段类型
            columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
            //转换字段名称，如 sys_name 变成 SysName
            columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
            //字段在数据库的注释
            columnClass.setColumnComment(resultSet.getString("REMARKS"));
            columnClassList.add(columnClass);
        }
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("model_column",columnClassList);
        generateFileByTemplate(templateName,mapperFile,dataMap);

    }


    /**
     * 生成DTO文件
     * @throws Exception
     */
    private void generateDTOFile() throws Exception{
        final String pageName = "dto\\";
        final String suffix = "DTO.java";
        final String path = diskPath + pageName + changeTableName + suffix;
        final String templateName = "DTO.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    /**
     * 生成控制层
     * @throws Exception
     */
    private void generateControllerFile() throws Exception{
        final String pageName = "controller\\";
        final String suffix = "Controller.java";
        final String path = diskPath + pageName + changeTableName + suffix;
        final String templateName = "Controller.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    /**
     * 生成业务实现层
     * @throws Exception
     */
    private void generateServiceImplFile() throws Exception{
        final String pageName = "service\\impl\\";
        final String suffix = "ServiceImpl.java";
        final String path = diskPath + pageName + changeTableName + suffix;
        final String templateName = "ServiceImpl.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    /**
     * 生成业务接口层
     * @throws Exception
     */
    private void generateServiceInterfaceFile() throws Exception{
        final String pageName = "service\\";
        final String suffix = "Service.java";
        final String path = diskPath + pageName + changeTableName + suffix;
        final String templateName = "Interface.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }



    private void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("table_name_small",tableName);
        dataMap.put("table_name",changeTableName);
        dataMap.put("author",AUTHOR);
        dataMap.put("date",CURRENT_DATE);
        dataMap.put("package_name",packageName);
        dataMap.put("table_annotation",tableAnnotation);
        dataMap.put("corePageName",corePageName);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
        template.process(dataMap,out);
    }



}
